package net.qiqbframework.eventhandling;


import net.qiqbframework.messaging.annotation.*;

import java.util.Optional;

public class AnnotationEventHandlerAdapter implements EventMessageHandler {

    private final AnnotatedHandlerInspector<Object> inspector;
    /**
     * 监听类
     */
    private final Class<?> listenerType;
    /**
     * 监听对象
     */
    private final Object annotatedEventListener;

    public AnnotationEventHandlerAdapter(Object annotatedEventListener, HandlerParameterResolverFactory parameterResolverFactory) {
        this(annotatedEventListener,
                parameterResolverFactory,
                (e, h) -> h,
                ClasspathHandlerDefinition.forClass(annotatedEventListener.getClass()));
    }

    /**
     * Wraps the given {@code annotatedEventListener}, allowing it to be subscribed to an Event Bus. The given {@code
     * parameterResolverFactory} is used to resolve parameter values for handler methods. Handler definition is used to
     * create concrete handlers.
     *
     * @param annotatedEventListener   the annotated event listener
     * @param parameterResolverFactory the strategy for resolving handler method parameter values
     * @param handlerDefinition        the handler definition used to create concrete handlers
     */
    public AnnotationEventHandlerAdapter(Object annotatedEventListener,
                                         HandlerParameterResolverFactory parameterResolverFactory,
                                         HandlerAttributesPostProcessor handlerAttributesPostProcessor,
                                         MessageHandlingMemberFactory handlerDefinition) {
        this.annotatedEventListener = annotatedEventListener;
        this.listenerType = annotatedEventListener.getClass();
        this.inspector = AnnotatedHandlerInspector.inspectType(annotatedEventListener.getClass(), parameterResolverFactory, handlerAttributesPostProcessor, handlerDefinition);
    }

    @Override
    public Object handle(EventMessage<?> event) throws Exception {
        Optional<MessageExecutableHandler> handler = inspector.getHandlers(listenerType)
                .filter(h -> h.canHandle(event))
                .findFirst();
        if (handler.isPresent()) {
            MessageHandlerInterceptorMemberChain<Object> interceptor = inspector.chainedInterceptor(listenerType);
            interceptor.handle(event, annotatedEventListener, handler.get());
        }

        return null;
    }





    @Override
    public Class<?> getTargetType() {
        return listenerType;
    }

}
